﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using System.IO;
using System.Security.Cryptography;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Text.RegularExpressions;
using static XQ.Framework.http.HttpHelper;
using System.Net.Http.Headers;

namespace XQ.Framework.WeChatPay
{
    
    /// <summary>
    /// 微信支付V3服务类
    /// </summary>
    public class WeChatPayV3Service
    {
        // 配置参数
        public string MchId { get; set; }             // 服务商商户号
        public string AppId { get; set; }             // 服务商AppID
        public string SubMchId { get; set; }          // 子商户号
        public string SubAppId { get; set; }          // 子商户AppID (可选)
        public string ApiKeyV3 { get; set; }          // API v3密钥
        public string CertSerialNo { get; set; }      // 证书序列号
        public string PrivateKey { get; set; }        // 商户私钥 (PEM格式)
        public string NotifyUrl { get; set; }         // 支付通知地址

        // 微信支付API域名
        private const string WECHAT_PAY_API = "https://api.mch.weixin.qq.com";

        /// <summary>
        /// 服务商模式JSAPI下单
        /// </summary>
        public async Task<Dictionary<string, string>> CreateJsapiOrder(
            string openId,
            string orderId,
            int totalFee,
            string description,
            bool isServiceMode = true)
        {
            var url = $"{WECHAT_PAY_API}/v3/pay/partner/transactions/jsapi";

            var body = new
            {
                sp_appid = AppId,
                sp_mchid = MchId,
                sub_appid = isServiceMode ? SubAppId : null,
                sub_mchid = isServiceMode ? SubMchId : null,
                description = description,
                out_trade_no = orderId,
                time_expire = DateTime.Now.AddMinutes(15).ToString("yyyy-MM-ddTHH:mm:sszzz"),
                amount = new
                {
                    total = totalFee,
                    currency = "CNY"
                },
                payer = new
                {
                    sub_openid = openId   // 服务商模式时使用子商户openid
                },
                notify_url = NotifyUrl
            };

            var response = await RequestV3Async(url, HttpMethod.Post, body);
            var result = JsonConvert.DeserializeObject<JObject>(response);

            if (result["prepay_id"] == null)
                throw new Exception($"下单失败: {result}");

            string prepayId = result["prepay_id"].ToString();
            return GenerateMiniProgramParams(prepayId, isServiceMode);
        }

        /// <summary>
        /// 生成小程序支付参数
        /// </summary>
        private Dictionary<string, string> GenerateMiniProgramParams(string prepayId, bool isServiceMode)
        {
            string timestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
            string nonceStr = Guid.NewGuid().ToString("N").Substring(0, 32);
            string package = $"prepay_id={prepayId}";

            // 服务商模式下，支付使用的appId是子商户AppId
            string appId = isServiceMode && !string.IsNullOrEmpty(SubAppId)
                ? SubAppId
                : AppId;

            // 构造签名串
            string message = $"{appId}\n{timestamp}\n{nonceStr}\n{package}\n";
            PrivateKey = GetWechatPrivateKey();
            string signature = Convert.ToBase64String(WeChatPayV3Signature.SignWithPrivateKey(message, PrivateKey));

            return new Dictionary<string, string>
            {
                ["appId"] = appId,
                ["timeStamp"] = timestamp,
                ["nonceStr"] = nonceStr,
                ["package"] = package,
                ["signType"] = "RSA",
                ["paySign"] = signature
            };
        }

       
        /// <summary>
        /// 服务商模式退款
        /// </summary>
        public async Task<JObject> CreateRefund(
            string transactionId,
            string outRefundNo,
            int totalFee,
            int refundFee,
            string reason = "")
        {
            var url = $"{WECHAT_PAY_API}/v3/refund/domestic/refunds";

            var body = new
            {
                transaction_id = transactionId,
                out_refund_no = outRefundNo,
                reason = reason,
                amount = new
                {
                    refund = refundFee,
                    total = totalFee,
                    currency = "CNY"
                }
            };

            var response = await RequestV3Async(url, HttpMethod.Post, body);
            return JsonConvert.DeserializeObject<JObject>(response);
        }

        //// 验证微信支付签名
        //private bool VerifySignature(string body, string signature, string nonce, string timestamp, string serialNo)
        //{
        //    // 1. 构造签名字符串
        //    string signString = $"{timestamp}\n{nonce}\n{body}\n";

        //    // 2. 获取微信支付平台证书（根据序列号）
        //    X509Certificate2 cert = GetWechatCertificate(serialNo);
        //    if (cert == null)
        //        throw new Exception($"未找到序列号[{serialNo}]的微信支付平台证书");

        //    // 3. 验证签名
        //    using (RSA rsa = cert.GetRSAPublicKey())
        //    {
        //        byte[] signBytes = Convert.FromBase64String(signature);
        //        byte[] dataBytes = Encoding.UTF8.GetBytes(signString);

        //        return rsa.VerifyData(
        //            dataBytes,
        //            signBytes,
        //            HashAlgorithmName.SHA256,
        //            RSASignaturePadding.Pkcs1
        //        );
        //    }
        //}

        /// <summary>
        /// 执行V3 API请求
        /// </summary>
        private async Task<string> RequestV3Async(string url, HttpMethod method, object body = null)
        {
            using (var handler = new HttpClientHandler())
            {
                // 配置证书 (退款/分账等敏感操作需要)
                if (url.Contains("/secapi/"))
                {
                    var cert = new X509Certificate2("path_to_cert.p12", "mch_id",
                        X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
                    //handler.ClientCertificates.Add(cert);


                }

                using (var client = new HttpClient(handler))
                {
                    try
                    {
                        //// 构造请求
                        //var request = new HttpRequestMessage(method, url);

                        // 添加认证头
                        string token = GenerateToken(method, url, body);

                        // 添加请求体
                        string json = JsonConvert.SerializeObject(body);


                        // 发送请求

                        //var response = await client.PostAsync(url, content);
                        //var result = await response.Content.ReadAsStringAsync();
                        var response = Request.HttpPostRequestForWechat($"WECHATPAY2-SHA256-RSA2048 {token}", CertSerialNo, url, json);
                       


                        return response;
                    }
                    catch (Exception ex) {

                        return ex.Message;
                    }
                }
            }
        }

        /// <summary>
        /// 生成认证Token
        /// </summary>
        private string GenerateToken(HttpMethod method, string url, object body = null)
        {
            string timestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
            string nonce = Guid.NewGuid().ToString("N");

            // 获取请求体 (GET请求无请求体)
            string bodyString = "";
            if (method != HttpMethod.Get && body != null)
                bodyString = JsonConvert.SerializeObject(body);

            // 构造签名串
            string path = new Uri(url).PathAndQuery;
            string message = $"{method.Method}\n{path}\n{timestamp}\n{nonce}\n{bodyString}\n";

            // 计算签名
            PrivateKey = GetWechatPrivateKey();
            string signature = WeChatPayV3Signature.GenerateSignature(message, PrivateKey);

            // 构造Token
            return $"mchid=\"{MchId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{CertSerialNo}\",signature=\"{signature}\"";
        }


        /// <summary>
        /// 获取微信支付平台公钥
        /// </summary>
        private string GetWechatPublicKey()
        {
            return @"-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQTf0jL9w3OvaV6z7moC
6gZPtMy+ZPaUMwxLpnmTImJCVzD4gO/MzRLcaXJ+VeDxAQK+2weIEo1oTssIaUM/
hDLMC/I5zIymPrgt152QM8GP6PvJQcUSsGp4NQzC3WoWcUQo6x2xq+cXjGo78rEL
6LAS4Y7XYBk6GeJxN4JIg0GUOjfebunVHFcm72M6kqZBtO2OpX2CWNqLsMvKBvw8
EIITWZFHnkH/If4ys5a42JLZcQ/QSGb0zN4RtEvYqiPiaimGT6Myca1tYUFX+TDp
GMbfGDP3g4FLz+h+FKJ0MQIDevWAFiKAZian/Z5wWqB1Me7SeZ9BMoRDxaKMGu/Y
kQIDAQAB
-----END PUBLIC KEY-----
";
        }

        private string GetWechatPrivateKey()
        {
            return @"-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC50SiX+dhDdy3J
aS5MO7fvbd1e6RtwIkLXId5rPmdsxk+0mxCFEj+cFgf50jCZGEDq/5bSR71uTHWi
3JmNFSfdgH6kep5OKw/wKFjBqLfstTsYeU3AeXSvLFNZbb/kgcQy1orfi8O0XD4g
sH8PjwRyL/6lKsKfNh8XdJ/ebZrslf7LQkLyq7quK0q8lLRnyUOfxX9CzIWSf7OR
29pbu/z8RtgU5uYWu7DDlrT3hWKYIGAwjX08ivyIMfWrwRJ6W8XYKlgSThoMpwMI
Y9T1y9MVVk5UXsrkVIztw+zguyuRdPhg4aCj9RoZal+st1Va7R1PEhWoHo1mCR4v
pjJ+buDrAgMBAAECggEAfOxdOi9CcbkCE1KfSaksc8+M8G4PgEfIYBHpEniV189L
bsSBSrWGBk3Zdt8UxRhFLLhAkYahmDHXNHLS2MLMVmI4wiOdojfZM0Asy6W+YWlG
HaIP38LH660FLC5YwCtt2C/clYXFQNBzBE8kXTVta8dQj4I77gXYyVAi2ssdSMg4
N9OkJmqaitHw8NhsDNwVVPY6gkI77L/bijANf4oC771+ENmpWfhP4lIcqTLpM0Eg
CHq7L9IuL9CMmbfwgu/UkGiz8QvB4MC9/e7y4mECqnp8xNMrDpXw+9CLcgS0x/W+
Tv4RvhJHdsBfN+C1z/xg+A1OejVtRnQS1VXOLTqkwQKBgQDv6EZJPE78neR6l9PY
mQKmSsgd8o78nsu2o+v0hz2P4H/FrCJlAXIxRzKrTwFfrb9aY37+7ECHqUFd2VZV
i/rhbQonAbFJLU8tgEZxOWDWt3yimGR+/VIrng0EX1qJO04HqYPiV8RH9QOzsNA8
rc7tzaQuJGib0QOBCBVSERvg6QKBgQDGSAmAeaQEYfdOjwDh6aRGW6OmSj1n9KJM
xhTCh3/IdXZYZctY+KT8t29E4WOTgjjvnqbFRuS9+b57pABfw67Gnz9+y8Y82OnR
ftYO4BH9ZGXFrN8U+T9p4IsyNgd3GrXKLakt8l0t2GdhfroXiIwKVzXbA32QXZWP
toqC7xjuswKBgQCRbgyteJGpMU2/wyn4s0iX5d1JyjBDkz+Kh/QRV6pJ/Z13BtIS
yL2ggbiFgG8kwP6unIHvpue3VTL64TUkxqZe4Oq2mqAN7BmDS69oE5BQmQpExnyl
PosBRd4+OE95wSmcG3aHTwz9Udnco+KX5gT6wx4zmn6PdjTZkzzZcuWjgQKBgHPE
a4fPfavxZus/I0zDlV5e8tWMUv33HyukG0rYwgrQSiCijm+L/QhwMU8OKY1eYs/E
2aolEji5MDYQMwe2wLzHDdOCNmQgYaQnYeOdf+NqUuFvZXBhdlzi9WKDmSg5OBqr
PjPNZgn2Z6XMz+odl2YSNSeCijVX7pLSCV0ZLH1xAoGBALx2NzjSvDoQyC1cP7+M
CzZYnYBTbyqzwzqRN6ZZyFVKr0W8oIPmzDLpBoi06rxaWa1yT48tXglbUFaN6cbH
bWM/a0qthn5m+IqdWJ3uB2JI34z/nfzPpWAuwXjdemp4h/8EK+r39BIX2dEQdfTz
KLe2TmNIoEcraQVID5Q3qtqa
-----END PRIVATE KEY-----";
        }
    }

    /// <summary>
    /// 分账接收方
    /// </summary>
    public class Receiver
    {
        [JsonProperty("type")]
        public string Type { get; set; } // MERCHANT_ID/PERSONAL_OPENID

        [JsonProperty("account")]
        public string Account { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; } // 需加密

        [JsonProperty("amount")]
        public int Amount { get; set; }

        [JsonProperty("description")]
        public string Description { get; set; }
    }
}
